package com.upbos.boot.sso.configuration;

import com.upbos.boot.sso.props.SsoConfigProps;
import com.upbos.boot.sso.annotation.ConditionalOnExistProperty;
import com.upbos.boot.sso.props.StorageCacheProps;
import com.upbos.boot.sso.props.StorageHttpProps;
import com.upbos.boot.sso.props.StorageLocalCacheProps;
import com.upbos.cache.SingleCacheManager;
import com.upbos.cache.props.CacheProps;
import com.upbos.cache.support.CaffeineCacheManager;
import com.upbos.sso.Constants;
import com.upbos.sso.filter.SsoFilter;
import com.upbos.sso.storage.SessionKickOutListener;
import com.upbos.sso.storage.StorageManager;
import com.upbos.sso.storage.impl.CacheStorageManager;
import com.upbos.sso.storage.impl.HttpStorageManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;

import javax.annotation.Resource;
import java.util.Map;


@Configuration
@EnableConfigurationProperties(value = {SsoConfigProps.class})
@ConditionalOnClass(SsoFilter.class)
public class StorageAutoConfiguration {

    @Resource
    private SsoConfigProps ssoConfigProps;

    @Resource
    private ApplicationContext applicationContext;

    private SingleCacheManager localCacheManager() {
        StorageLocalCacheProps localCacheProps = ssoConfigProps.getStorageLocalCache();
        if (localCacheProps == null) {
            localCacheProps = new StorageLocalCacheProps();
        }
        if (!localCacheProps.isEnable()) {
            return null;
        }
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        CacheProps cacheProps = new CacheProps();
        cacheProps.setCacheName(localCacheProps.getCacheName());
        cacheProps.setExpireTime(localCacheProps.getExpireTime());
        cacheProps.setExpirePolicy(localCacheProps.getExpirePolicy());
        cacheManager.setCache(cacheProps);
        return cacheManager;
    }

    @Bean
    @Order(1)
    @ConditionalOnExistProperty(prefix = "sso", name = Constants.STORAGE_HTTP)
    public StorageManager httpStorageManager() {
        HttpStorageManager httpStorageManager = new HttpStorageManager();
        httpStorageManager.setLocalCacheManager(localCacheManager());
        StorageHttpProps httpProps = ssoConfigProps.getStorageHttp();
        if (httpProps == null) {
            return httpStorageManager;
        }
        if (httpProps.getTokenServerUrl() != null) {
            httpStorageManager.setTokenServerUrl(httpProps.getTokenServerUrl());
        }
        return httpStorageManager;
    }

    @Bean
    @Primary
    @Order(21474611)
    @ConditionalOnMissingBean(StorageManager.class)
    public StorageManager cacheStorageManager(SingleCacheManager singleCacheManager) {

        CacheStorageManager cacheStorageManager = new CacheStorageManager();
        cacheStorageManager.setSingleCacheManager(singleCacheManager);
        cacheStorageManager.setLocalCacheManager(localCacheManager());
        Map<String, SessionKickOutListener> map = applicationContext.getBeansOfType(SessionKickOutListener.class);
        map.forEach((s, sessionKickOutListener) -> cacheStorageManager.setSessionKickOutListener(sessionKickOutListener));
        StorageCacheProps cacheProps = ssoConfigProps.getStorageCache();
        if (cacheProps == null) {
            return cacheStorageManager;
        }
        if (cacheProps.getSingleSession() != null) {
            cacheStorageManager.setSingleSession(cacheProps.getSingleSession());
        }
        if (cacheProps.getTokenCacheName() != null) {
            cacheStorageManager.setTokenCacheName(cacheProps.getTokenCacheName());
        }

        if (cacheProps.getTokenCacheNames() != null) {
            cacheStorageManager.setTokenCacheNames(cacheProps.getTokenCacheNames());
        }

        cacheStorageManager.setSingleCacheManager(singleCacheManager);

        return cacheStorageManager;
    }


}